﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;
using ServerAdapter.WcfGeebaService;
using ServerAdapter;

namespace WPFGeebaClient
{
    // delegates used to call MainForm functions from worker thread
       public delegate void DelegateThreadWork();
 
    public partial class MainWindow : Window
    {

        #region DataMembers

        public static ServerAdapter.SAdapter server;
        private GSubForum sf;
        public static User user;
        private ClientListener listener;
        Thread m_WorkerThread;
        RegisterWindow rw;

        // Delegate instances used to cal user interface functions 
        // from worker thread:
        public DelegateThreadWork m_DelegateDoWork;

        #endregion DataMembers

        public MainWindow()
        {
            InitializeComponent();
            this.Closed += new EventHandler(MainWindow_Closed);

            listener = new ClientListener();
            listener.OnUpdateFromServer += new ClientListener.OnUpdate(listener_OnUpdateFromServer);
            listener.OnEditMessageFromServer += new ClientListener.OnEditMessage(listener_OnEditMessageFromServer);
            server = new ServerAdapter.SAdapter(listener);

            user = server.serverEntry();
            server.serverSubscribe(user.username);

            userNameLabel.Content = user.username;
            privilagesLabel.Content = user.userType;
            sf = new GSubForum();
            rw = new RegisterWindow(user, server);
            loadSubforumsFromServer();
            loadOnlineUserCounterFromServer();
        } 

        #region Events

        void MainWindow_Closed(object sender, EventArgs e)
        {
            if (user.userType != UserType.Guest)
            {
                server.serverLogout((Member)user);
            }
        }

        private void listener_OnUpdateFromServer(GThread message, DateTime timestamp, bool isNotification)
        {
            addNewThreadBtn.IsEnabled = true;
            loadSubfrmThreads();

            subjectText.Text = "";
            contentText.Text = "";

            if (isNotification)
            {
                MessageBox.Show("Notice: message " + message._id + " at " + timestamp);  
            }
        }

        private void listener_OnEditMessageFromServer(string subforumTopic, GThread message, DateTime timestamp)
        {
            MessageBox.Show("Message Edit change push notification: subforumTopic:" + subforumTopic + ",content: \"" + message._content + "\"" + timestamp);
            if (this.sf.topic != null && this.sf.topic.Equals(subforumTopic))
            {
                foreach (threadControl thread in this.threadsTreeView.Items)
                {
                    if (Int32.Parse(thread.tidTxt.Content.ToString()) == message._id)
                    {
                        //MessageBox.Show("Message is shown -> changing content");
                        thread.contentTxt.Content = message._content;
                        thread.Background = new SolidColorBrush(Colors.GreenYellow);
                        this.threadsTreeView.Items.Refresh();
                    }
                }
            }

        }

        private void subforumsList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (((SubfourmControl)((ListBox)sender).SelectedItem) != null)
            {
                sf.topic = (string)((SubfourmControl)((ListBox)sender).SelectedItem).txtTopic.Content;
                loadSubfrmThreads();
            }

        }

        private void loginBtn_Click(object sender, RoutedEventArgs e)
        {
            if (((string)loginBtn.Content) == "logout")
            {
                User userFromServer = server.serverLogout(user);
                if (userFromServer != null)
                {
                    logout(userFromServer);
                }
            }
            else
            {
                if (usernameTxt.Text != null && usernameTxt.Text != "" && passwordBox1.Password != null && passwordBox1.Password != "")
                {
                    Member tempUsr = server.serverLogin(user, usernameTxt.Text, passwordBox1.Password);
                    if (tempUsr != null && userNameLabel.Content != null)
                    {
                        login(tempUsr);
                    }
                    else
                    {
                        MessageBox.Show("Error in username or password.");
                    }
                }
                else
                {
                    MessageBox.Show("username and password can not be empty.");
                }

            }
            passwordBox1.Clear();
            usernameTxt.Clear();
        }
        private void signBtn_Click(object sender, RoutedEventArgs e)
        {
            if (user != null && user.userType != UserType.Guest)
            {
                MessageBox.Show("Must logout first!");
            }
            else
            {
                rw.ClearValues(); 
                rw.Show();
                rw.Focus();
                passwordBox1.Clear();
                usernameTxt.Clear();
            }
        }

        private void removeSubforumsBtn_Click(object sender, RoutedEventArgs e)
        {
            var itemToDelete = subforumsList.SelectedItem;
            if (itemToDelete != null)
            {
                if (!server.serverRemoveSubForum((Member)user, (string)((SubfourmControl)itemToDelete).txtTopic.Content))
                {
                    MessageBox.Show("Error is removing");
                }
                else
                {
                    subforumsList.Items.Remove(itemToDelete);
                }
            }
        }
        private void addSubfrmBtn_Click(object sender, RoutedEventArgs e)
        {
            AddNewSubforum addWin = new AddNewSubforum(server, subforumsList);
            addWin.Show();
            //subforumsList.Items.Add(new SubfourmControl("new", "0"));

        }
        private void addNewThreadBtn_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (user.userType == UserType.Guest)
                {
                    MessageBox.Show("You must log in to publish posts/threads.");
                    return;
                }

                if (commentCheckBox.IsChecked.Value)
                {
                    // comment
                    GPost newComment = new GPost();
                    newComment._publisher = (Member)user;
                    newComment._publisher.username = user.username;
                    newComment._publisher.userType = user.userType;
                    newComment._subject = subjectText.Text;
                    newComment._content = contentText.Text;

                    // create worker thread instance
                    m_WorkerThread = new Thread(new ParameterizedThreadStart(this.WorkerThreadFunctionComment));
                    m_WorkerThread.Name = "add new comment";   // looks nice in Output window
                    addNewThreadBtn.IsEnabled = false;
                    int t_tid = Int32.Parse(((System.Windows.Controls.ContentControl)(((WPFGeebaClient.ThreadControl)(((System.Windows.Controls.HeaderedItemsControl)(this.threadsTreeView.SelectedItem)).Header)).tidTxt)).Content.ToString());
                    List<Object> list = new List<Object>();
                    list.Add(newComment);
                    list.Add(t_tid);

                    m_WorkerThread.Start(list);
                }
                else
                {   // new thread
                    GThread newMsg = new GThread();

                    newMsg._publisher = (Member)user;
                    newMsg._publisher.username = user.username;
                    newMsg._publisher.userType = user.userType;
                    newMsg._subject = subjectText.Text;
                    newMsg._content = contentText.Text;

                    // create worker thread instance
                    m_WorkerThread = new Thread(new ParameterizedThreadStart(this.WorkerThreadFunction));
                    m_WorkerThread.Name = "add new message";   // looks nice in Output window
                    addNewThreadBtn.IsEnabled = false;
                    m_WorkerThread.Start(newMsg);
                }
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message);
            }
        }

        private void refreshSubforumsBtn_Click(object sender, RoutedEventArgs e)
        {
            subforumsList.Items.Clear();
            loadSubforumsFromServer();
            loadOnlineUserCounterFromServer();
        }

        #endregion

        #region Help Methods

        private void loadSubforumsFromServer()
        {
            try
            {
                subforumsList.Items.Clear();
                List<GSubForum> subforums = server.serverGetSubForums();
                foreach (GSubForum subfourm in subforums)
                {
                    int threadCount = 0;
                    if (user != null && user.userType == UserType.Admin)
                    {
                        threadCount = server.serverGetThreadCount((Member)user, subfourm.topic);
                    }

                    subforumsList.Items.Add(new SubfourmControl(subfourm.topic, threadCount.ToString()));
                }
            }
            catch (Exception e)
            {
                string msg = "";
                if (e != null)
                {
                    msg = e.Message;
                }
                MessageBox.Show("loadSubforumsFromServer Error! " + msg);
            }
        }
        private void loadOnlineUserCounterFromServer()
        {
            try
            {
                labelOnlineUsersCount.Content = server.getOnlineUserCount();
            }
            catch (Exception e)
            {
                MessageBox.Show("Error loadOnlineUserCounterFromServer" + e.Message);
            }

        }
        private void loadSubfrmThreads()
        {
            threadsTreeView.Items.Clear();
            //treeViewThreads.Items.Clear();
            if (sf != null && sf.topic != null)
            {
                List<GThread> threads = server.serverGetThreads(sf);
                 threads = threads.OrderByDescending(thread => thread._modifiedDate).ToList<GThread>();
                foreach (GThread thread in threads)
                {
                    //threadsListBox.Items.Add(new threadControl(thread._id, thread._subject, thread._content, thread._publisher.username, thread._modifiedDate.ToShortDateString() + " " + thread._modifiedDate.ToShortTimeString(), server));
                    //threadsTreeView.Items.Add(new threadControl(thread, sf.topic));//, treeViewThreads));
                    TreeViewItem tvi = new TreeViewItem();
                    tvi.Header = new ThreadControl(user, thread);//, topic);
                    threadsTreeView.Items.Add(tvi);
                    //treeViewThreads.Items.Add(new threadControl(thread, currSubForum.topic, treeViewThreads));
                    //TreeViewItem item = new TreeViewItem();
                    //item.Header = thread._subject + " - "+ thread._content;
                    //item.Items.Add(new threadControl(thread, currSubForum.topic, item));
                    //treeViewThreads.Items.Add(item);
                }
            }
            if (user.userType != UserType.Guest)
            {
                expanderAddThread.Visibility = System.Windows.Visibility.Visible;
            }
            else
            {
                expanderAddThread.Visibility = System.Windows.Visibility.Collapsed;
            }
            
        }
        private void logout(User userFromServer)
        {
            user = userFromServer;
            userNameLabel.Content = user.username;
            privilagesLabel.Content = user.userType;

            this.txtGetMemberThreadCount.Visibility = System.Windows.Visibility.Collapsed;
            this.btnGetMemberThreadCount.Visibility = System.Windows.Visibility.Collapsed;
            this.labelMemberGetMsgCount.Visibility = System.Windows.Visibility.Collapsed;
            //addSubfrmBtn.Visibility = System.Windows.Visibility.Hidden;
            //removeSubforumsBtn.Visibility = System.Windows.Visibility.Hidden;
            expanderAddThread.Visibility = System.Windows.Visibility.Collapsed;
            loginBtn.Content = "login";
            loadSubforumsFromServer();
            loadOnlineUserCounterFromServer();
        }
        private void login(User tempUsr)
        {
            user = tempUsr;
            userNameLabel.Content = user.username;
            privilagesLabel.Content = user.userType;
            //addSubfrmBtn.Visibility = System.Windows.Visibility.Visible;
            //removeSubforumsBtn.Visibility = System.Windows.Visibility.Visible;
            //expanderAddThread.Visibility = System.Windows.Visibility.Visible;
            loginBtn.Content = "logout";
            loadOnlineUserCounterFromServer();
            loadSubforumsFromServer();
            server.serverSubscribe(user.username);
            if (user.userType == UserType.Admin)
            {
                this.txtGetMemberThreadCount.Visibility = System.Windows.Visibility.Visible;
                this.btnGetMemberThreadCount.Visibility = System.Windows.Visibility.Visible;
                this.labelMemberGetMsgCount.Visibility = System.Windows.Visibility.Visible;
            }
        }
        private void ShowThreads(string topic, List<GThread> threads)
        {
            threadsTreeView.Items.Clear();
            if (topic != null && threads != null)
            {
                threads = threads.OrderByDescending(thread => thread._modifiedDate).ToList<GThread>();
                foreach (GThread thread in threads)
                {
                    TreeViewItem tvi = new TreeViewItem();
                    tvi.Header = new ThreadControl(user, thread);//, topic);
                    threadsTreeView.Items.Add(tvi);
                }
            }
        }
        

        #endregion

        // Worker thread function.
        // Called indirectly from btnStartThread_Click
        private void WorkerThreadFunction(Object newMsg)
        {
            try
            {
                server.serverPublish((Member)user, sf.topic, (GThread)newMsg);
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message);
            }
        }

        // Worker thread function.
        // Called indirectly from btnStartThread_Click
        private void WorkerThreadFunctionComment(Object list)
        {
            server.commentOnThread((Member)user, (GPost)(((List<Object>)list)[0]), sf.topic, (int)(((List<Object>)list)[1]));
        }

        private void contentSearchBtn_Click(object sender, RoutedEventArgs e)
        {
            
        }

        private void threadsTreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            if (e.NewValue != null)
            {
                int tid = Int16.Parse(((System.Windows.Controls.ContentControl)(((WPFGeebaClient.ThreadControl)(((System.Windows.Controls.HeaderedItemsControl)(e.NewValue)).Header)).tidTxt)).Content.ToString());
                List<GPost> posts = server.serverGetComments(user, ((SubfourmControl)(this.subforumsList.SelectedItem)).txtTopic.Content.ToString(), tid).ToList();
                posts = posts.OrderByDescending(post => post._modifiedDate).ToList<GPost>();
                TreeViewItem tviControl = ((TreeViewItem)((TreeView)threadsTreeView).SelectedItem);

                tviControl.Items.Clear();

                foreach (GPost post in posts)
                {
                    if (((Int32)((ThreadControl)tviControl.Header).tidTxt.Content) == tid)
                    {
                        TreeViewItem tvi = new TreeViewItem();
                        tvi.Header = new ThreadControl(user, post);//, e.UserState.ToString());
                        tviControl.Items.Add(tvi);
                    }
                }

                tviControl.IsExpanded = true;
            }
        }

        private void btnGetMemberThreadCount_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                MessageBox.Show(txtGetMemberThreadCount.Text + " published " + server.serverGetMemberThreadCount((Member)user, txtGetMemberThreadCount.Text) + " Messeges.");
            }
            catch(Exception exc)
            {
                MessageBox.Show(exc.Message);
            }
        }
    }
}
